/**************************************************************
                    fpc_load.c
**************************************************************/
#include <fcntl.h>
#include <float.h>
#include "clam.h"
#include "mtp.h"
#include "seq.h"
#define DELETED 1
#define FPMAX 500 /* number of fp map that can be displayed (fp-> fingerprint) */
#define graphQuery messQuery

extern BOOL fpcreadflag,writeaccess;
extern int Zbatch_flag, Zkill_seq;

extern void getdatehead(), Pz_init(), unbury();
extern void Pz_default(), ZloadCpM(), ZbuildCpM(), ZsetCpM(), ZloadBuild();
extern int filCheck(), grantaccess();
extern void load_layout();     /*fred 4/14/03*/
extern void write_fpp_file();  /*fred 4/15/03*/
extern void update_fp_class_pars(void);
extern void redo_sequence_placements();

int Marker_clone_max;          /* cari 14.5.4 used in ace_merge also */
int max_clonesz=0, max_markersz=0, max_seqsz = 0; /* 3/8/1, used in ctgpick.c only */
int readfpc();
int dequote();
void getcomment();
void SetCtgForMatchingClones2();
void sortoutmarkersman(void);
void setmarkerposman(void);
void settime(struct mytime *mytime);
void markercorrect(void);
void markersinctgcount(void);
void getfppdata(void);
void contigsAlloc(int ctg);
void remove_old_project(void);
void read_filter(void);
FILE *graphQueryOpen();
void suffixremove(char*);

BOOL fppFind(Array a, char *s, int *ip, BOOL (* order)());
BOOL fppInsert(Array a, char *s, int *index, BOOL (*order)());
BOOL cloneOrder(void *s, void *b);
BOOL markerOrder(void *s, void *b);
extern  BOOL  dataloaded;
extern BOOL merging,firstread;
extern int cloneindex[FPMAX];
extern char timestamp[255];
extern int defaultflag;


/*******************************************************************
                  DEF: check_GSC
********************************************************************/
static void check_GSC()
{
char str1[2048];
FILE *T;

  if(strlen(dirName)>0) sprintf(str1,"%s/Image/GSC_is_running",dirName);
  else sprintf(str1,"Image/GSC_is_running");
  if ((T=fopen(str1,"r"))!=NULL) {
      fclose(T);
      sprintf(str1,
      "The project is being updated by a FPC-GSC cronjob.\nYou MUST not Update .cor.\nDo you want to continue?");
      if(!messQuery(str1)) {
        fprintf(stderr,"FPC terminated due to GSC_is_running file indicating FPC-GSC cronjob.\n");
        exit(1);
      }
  }

}
/*******************************************************************
                  DEF: init_new_project
********************************************************************/
static void init_new_project()
{
  int i;
  defaultflag = DEFAULTFLAG;
  acedata  = arrayReCreate (acedata, 10, CLONE) ;
  markerdata = arrayReCreate (markerdata, 10 , MARKER);
  if(filterdata) arrayDestroy(filterdata);
  filterdata = 0;
  Proj.filterfile[0] = '\0';
  Proj.mapname[0] = '\0';
  Proj.anchor_label[0] = '\0';
  Proj.label_abbrev[0] = '\0';
  Proj.generic_grpnames = 0;
  Proj.default_page_size=3000;
  max_contig=0;
  for(i=0;i<FPMAX;i++) cloneindex[i]= -1;
  contigsAlloc(0);
  dataloaded = TRUE;
  num_of_bands=0;
  Pz_default();
  Pz_init();
  max_clonesz = CLONE_SZ;
  max_markersz = MARKER_SZ;
  SeqProps.min_clones = 5;
  SeqProps.min_ctgs = 2;
  SeqProps.window_size = 250;
  SeqProps.use_unique = 1;
  SeqProps.endmatch_check = 1;
  strcpy(SeqProps.search_name,"");
}
/*******************************************************************
                  DEF: new project (called from File... in fpp2.c
********************************************************************/
BOOL openandreadnew(void)
{
  FILE *fpace;
  char out2[120];

  fpace = graphQueryOpen(dirName, fileName, "fpc","w","Enter new project name");
  suffixremove(fileName);

  if(fpace!=0){
    getdatehead(out2);
    fprintf (fpace, "// fpc project %s\n", fileName) ;
    fprintf (fpace, "// %s\n", out2) ;
    sprintf (timestamp,"// %s\n", out2) ;
    fprintf (fpace, "// Clones 0  Markers 0  Bands 0\n") ;
    filclose(fpace);
    return TRUE;
  }
  else {
    displaymess("Unable to create new project");
    return(FALSE);
  }
}

void newproject()
{
char str1[MAXPATHLEN+100];

  if (dataloaded && writeaccess)
      grantaccess(); /* unlocks */

  if(!openandreadnew()) return;
  if(dataloaded) remove_old_project();

  if(strlen(dirName)>0) sprintf(str1,"touch %s/%s.cor",dirName,fileName);
  else sprintf(str1,"touch %s.cor",fileName);
  system(str1);

  if(strlen(dirName)>0) sprintf(str1,"%s/Bands",dirName);
  else sprintf(str1,"Bands");
  if(!filCheck(str1,"d")){
    if(strlen(dirName)==0) sprintf(str1,"mkdir ./Bands");
    else sprintf(str1,"mkdir %s%s",dirName,"/Bands");
    printf("Adding Bands Directory\n");
    system(str1);
  }
  if(strlen(dirName)>0) sprintf(str1,"%s/Image",dirName);
  else sprintf(str1,"Image");
  if(!filCheck(str1,"d")){
    if(strlen(dirName)==0) sprintf(str1,"mkdir ./Image");
    else sprintf(str1,"mkdir %s%s",dirName,"/Image");
    printf("Adding Image Directory\n");
    system(str1);
  }
  init_new_project();
  getfppdata();   /*fred 5/7/03*/
  displaymess("New project is initalized.");
  menu_main();
}

/********************************************************************/
int get_fpc_marker(char *junk)
{
     if(strstr(junk,"STS")) return markSTS;
     else if(strstr(junk,"YAC")) return markYAC;
     else if(strstr(junk,"End")) return markEND;
     else if(strstr(junk,"Probe")) return markPROBE;
     else if(strstr(junk,"Locus")) return markLOCUS;
     else if(strstr(junk,"Clone")) return markCLONE;
     else if(strstr(junk,"Fosmid")) return markFOSMID;
     else if(strstr(junk,"Cosmid")) return markCOSMID;
     else if(strstr(junk,"BAC")) return markBAC;
     else if(strstr(junk,"PAC")) return markPAC;
     else if(strstr(junk,"cDNA")) return markCDNA;
     else if(strstr(junk,"PCR")) return markPCR;
     else if(strstr(junk,"SNP")) return markSNP;
     else if(strstr(junk,"eMRK")) return markeMRK;
     else if(strstr(junk,"eBAC")) return markeBAC;
     else if(strstr(junk,"TC")) return markTC;
     else if(strstr(junk,"SSR")) return markSSR;
     else if(strstr(junk,"RFLP")) return markRFLP;
     else if(strstr(junk,"OVERGO")) return markOVERGO;
     else if(strstr(junk,"REP")) return markREP;
     else return -1;
}
void markerdataprintout()
{
  int i;
  MARKER *marker;
  struct markerctgpos *pos;

  printf("**************************************\n");
  for(i=0;i<arrayMax(markerdata);i++){
    marker = arrp(markerdata,i,MARKER);
    printf("%s",marker->marker);
    pos= marker->pos;
    while(pos!=NULL){
      printf("| ctg %d, %d |",pos->ctg,pos->pos);
      pos=pos->next;
    }
    printf("\n");
  }
}

/*******************************************************************
                  DEF: openandreadfile
********************************************************************/
int openandreadfpc(void)
{
FILE *fpace;
  fpace = graphQueryOpen(dirName, fileName, "fpc","r","Choose project to load");
  suffixremove(fileName);
  if(fpace!=0)
    return readfpc(fpace);
  else
    return(-1);
}

/*******************************************************************
                     DEF: readfpc
********************************************************************/
int readfpc(fpace)
FILE *fpace;
{
  char junk[355], name[200];
  int i, j, k;
  int maxindex = 0, buried = 0;
  int index = 0, cnt_markers=0;
  BOOL markerstuff, contigstuff;
  struct fpdata *currfp=NULL;
  struct remark *last=NULL;
  CLONE clone, *clp;
  struct markerclone *markclptr;
  struct marker *marker, pt;
  struct markertop *mtop;
  int markertype= 0, orig_clones =0, ctg_sets=1;
  BOOL addit=FALSE;
  struct markerctgpos *posptr=NULL;
  int flag, line=0, ctype,index3,oldmax, tot_markers=0;
  char *pos, *ptr;
  int weak;
  BOOL new;
  float ftmp;
  char type[20], status[20];
  Array markerdata2;
  float x;
  char tmp[50], *tmp2;
  int fwFlag=0;
  char tmpDQ[10];
  char* pch;

  check_GSC();

  Pz_default();

  oldmax = max_contig;
  max_contig=0;
  num_of_bands = 0;
  singleton = 0;
  if(fgets(junk,255,fpace) == NULL) {
     if (!Zbatch_flag) displaymess("The file is empty; assume new project");
     init_new_project();
     return TRUE;
  }
  line++;
  if (strstr(junk,"fpp")==0 && strstr(junk, "fpc")==0){
    if (!Zbatch_flag) displaymess("ERROR Not a FPC file\n");
    return FALSE;
  }

  tot_clones = tot_bands = index = orig_clones = 0;
  max_contig=1000;
  Proj.default_page_size=3000;
  Pz.fp_class = AGAROSE; // default value, for files with older format
  SeqProps.min_clones = 5;
  SeqProps.min_ctgs = 2;
  SeqProps.window_size = 250;
  SeqProps.top_n = 0;
  SeqProps.use_unique = 1;
  SeqProps.search_placed = 1;
  SeqProps.search_multiplaced = 0;
  SeqProps.search_ends = 0;


  seq_info_files = 0;

/*************************************************************************
 Parse header
************************************************************************/
  while (junk[0] == '/') { /* read and print comments at beginning */
    if (!Zbatch_flag)      /* cari 12/15/03 */
        fprintf(stdout,"%s", junk);
    if(strstr(junk,"clones,"))
        sscanf(junk,"// %d clones, %d",&tot_clones,&tot_bands);
    else if(strstr(junk,"// Contigs"))
        sscanf(junk,"// Contigs %d  Clones %d  Markers %d  Bands %d",
                 &max_contig, &tot_clones, &index, &Proj.tot_bands);
    else if(strstr(junk,"Clone")) /* FIX 17june99 obsolete after 4.4 */
        sscanf(junk,"//  Clones %d  Markers %d  Bands %d",
                 &tot_clones, &tot_markers, &Proj.tot_bands);
    else if(strstr(junk,"AvgBand")) {
      if((ptr = strstr(junk,"Framework"))) sscanf(ptr,"Framework %s",Proj.mapname);
      if((ptr = strstr(junk,"Label"))) sscanf(ptr,"Label %s",Proj.anchor_label);
      if((ptr = strstr(junk,"Abbrev"))) sscanf(ptr,"Abbrev %s",Proj.label_abbrev);
      if (strstr(junk,"generic_grpnames")) Proj.generic_grpnames = 1;
      if((ptr = strstr(junk,"AvgBand"))) sscanf(ptr,"AvgBand %d",&Proj.avgbandsize);
      if((ptr = strstr(junk,"Genome"))) sscanf(ptr,"Genome %f",&Proj.genomesize);
      if((ptr = strstr(junk,"AvgInsert"))) sscanf(ptr,"AvgInsert %d",
                 &Proj.avginsertsize);
    }
    else if((strstr(junk,"// Framework"))) { /* obsolete */
      Proj.avgbandsize=3000;
      Proj.genomesize=0;
      sscanf(junk,"// Framework %s %d %f", Proj.mapname, &Proj.avgbandsize,
                 &Proj.genomesize);
    }
    else if((strstr(junk,"Date:"))) strcpy(timestamp,junk);
    else if((strstr(junk,"Unc"))) sscanf(junk,"// Unc %s",Proj.uncfile);
    else if((strstr(junk,"Filter"))){ /*obsolete */
      sscanf(junk,"// Filter %s",Proj.filterfile);
      read_filter();
    }
    else if ((strstr(junk,"Vector"))){
      sscanf(junk,"// Vector %s",Proj.filterfile);
      read_filter();
    }
    else if ((strstr(junk,"Configure"))) {
      int precompute = Pz.precompute;
      sscanf(junk,"// Configure %d",&defaultflag);
      if ((strstr(junk,"Variable"))) Proj.variable = 1;
      if ((strstr(junk,"EQ2"))) Proj.eq2 = 1;
      else if ((strstr(junk,"EQ3"))) Proj.eq2 = 2; /* true sulston */
      if ((ptr = strstr(junk,"Tol"))) {
            sscanf(ptr,"Tol %d",&Pz.tol);
      }
      if((ptr = strstr(junk,"Cut"))) sscanf(ptr,"Cut %lf",&Pz.cutFlt);
      if((ptr = strstr(junk,"Apx"))) sscanf(ptr,"Apx %f",&Pz.burFlt);
      if((ptr = strstr(junk,"Gel"))) sscanf(ptr,"Gel %d",&Proj.gel_len);
      if((ptr = strstr(junk,"End"))) sscanf(ptr,"End %d",&Pz.fromendInt);
      if((ptr = strstr(junk,"SeqEnd"))) sscanf(ptr,"End %d",&Pz.seq_fromendInt);
      if((ptr = strstr(junk,"Kill"))) sscanf(ptr,"Kill %d",&Pz.killInt);
      if((ptr = strstr(junk,"Log"))) sscanf(ptr,"Log %d",&Pz.logFlag);
      if((ptr = strstr(junk,"Std"))) sscanf(ptr,"Std %d",&Pz.stdFlag);
      if((ptr = strstr(junk,"Best"))) sscanf(ptr,"Best %d",&Pz.bestInt);
      if((ptr = strstr(junk,"Bad"))) sscanf(ptr,"Bad %d", &Pz.diffInt);
      if((ptr = strstr(junk,"Page"))) sscanf(ptr,"Page %d",&Proj.default_page_size);
      if((ptr = strstr(junk,"Match"))) sscanf(ptr,"Match %d",&Pz.mergeMatches);
      if((ptr = strstr(junk,"FW"))) sscanf(ptr,"FW %d", &fwFlag);
      if (strstr(junk, "agarose")) Pz.fp_class = AGAROSE;
      if (strstr(junk, "hicf")) Pz.fp_class = HICF;
         /* pre V4 */
      if((ptr = strstr(junk,"Diff"))) {
         sscanf(ptr,"Diff %f %f",&ftmp, &Pz.burFlt);
         defaultflag &= 128;
      }
      update_fp_class_pars();
      Pz.precompute = precompute; // don't set this value on the basis of
                                  // agarose/hicf key in FPC file
    }
    else if ((strstr(junk,"// CpM"))) {
         ZloadCpM(junk);
         if (addit) {
            ftmp = Bd.cutoff;
            ZbuildCpM();
            Bd.cutoff = ftmp;
            ZsetCpM();
         }
    }
    else if((strstr(junk,"// Build Date"))) { /* obsolete for v4.6.1 */
      if((ptr = strstr(junk,"Date"))) sscanf(ptr,"Date %d/%d/%d %d:%d",
          &Bd.date.day, &Bd.date.month, &Bd.date.year,
          &Bd.date.hour, &Bd.date.minute);
      if((ptr = strstr(junk,"Cut"))) sscanf(ptr,"Cut %lf",&Bd.cutoff);
      if((ptr = strstr(junk,"CpM"))) Bd.useFlag=TRUE;
      if((ptr = strstr(junk,"AutoRemark"))) Proj.automsg=TRUE;
      else Proj.automsg=FALSE;
      addit=TRUE;
    }
    else if((strstr(junk,"// Build"))) ZloadBuild(junk);
    else if ((strstr(junk,"// Clip"))) {
      sscanf(junk,"// Clip(%d %d) MinMax(%d %d)",
         &Proj.MinClip, &Proj.MaxClip, &Pz.minVal, &Pz.maxVal);
              /* CAS 15feb04 - add precompute and useseq, remove AutoRemark */
      if((ptr = strstr(junk,"Precompute"))) Pz.precompute=1;
      else Pz.precompute=0;
      if((ptr = strstr(junk,"UseSeq"))) Zkill_seq=1;
      else Zkill_seq=0;

          /* cari - added 12/12/03 for V7.2  WN modified for %DQ 02/04 */
      if((ptr = strstr(junk,"DQer"))) {
        /* the scanf has to scan a string up to, not including, the next comma */
        sscanf(ptr,"DQer(%[^,],%d),",tmpDQ, &Pz.DQstep);
        pch = strchr(tmpDQ,'%');
        if (0 != pch) {
          Pz.DQusePct = 1;
          *pch = 0;
        }
        Pz.DQnumq = atoi(tmpDQ);
      }
    }
    else if (strstr(junk, "// MTP") != NULL) {
        mtp_load_configuration(junk);
    }
    else if (strstr(junk, "// SEQ_") != NULL) {
        sscanf(junk,"// SEQ_min_clones %d SEQ_min_ctgs %d SEQ_winsize %d SEQ_topn %d SEQ_endmatch %d",
            &SeqProps.min_clones, &SeqProps.min_ctgs,&SeqProps.window_size,
                        &SeqProps.top_n,&SeqProps.endmatch_check);
    }


    if(fgets(junk,255,fpace) == NULL) {
	acedata = 0;
        printf("ERROR reading line (Okay if this is a newly created project)\n");
        if (Zbatch_flag) {
            fp_class_t fp_class = Pz.fp_class;
            int precompute = Pz.precompute;
            init_new_project();
            Pz.fp_class = fp_class;
            Pz.precompute = precompute;
            return TRUE;
        }
	if(messQuery("Is this a newly created project")){
         fp_class_t fp_class = Pz.fp_class;
         int precompute = Pz.precompute;
         init_new_project();
         Pz.fp_class = fp_class;
         Pz.precompute = precompute;
         return TRUE;
	}
	else{
	  messout("ERROR reading Line. And not a new project. Therefore Not valid");
	  return FALSE;
	}
    }
    line++;
  }
  if(tot_clones > 0) acedata  = arrayReCreate (acedata, tot_clones, CLONE) ;
  else acedata  = arrayReCreate (acedata, 10, CLONE) ;
  listroot = NULL;

  if(!projmerge) {
    if (tot_markers>0) markerdata = arrayReCreate (markerdata, tot_markers, MARKER);
    else markerdata = arrayReCreate (markerdata, 10 , MARKER);
  }
  firstread = TRUE;
  orig_clones = tot_clones;

  tot_clones = 0;
  contigsAlloc(max_contig); /* initializes fields */

  /*Backwards compatibility*/
  if(fwFlag){
    strcpy(Proj.anchor_label,"Chromosome");
    strcpy(Proj.label_abbrev,"Chr");
  }

/*************************************************************************
 Parse clones
************************************************************************/
            /* this is just for reading in a fpc from Save_Contig_as_FPC*/
NEXT_SET: ; /*  which has multiple sets of data */

  contigstuff = markerstuff = FALSE;
  index = -1;

  while(fgets(junk,255,fpace) != NULL && !markerstuff){
      line++;
	  /* sness */
      /*for (i=0; i<255 && junk[i] == ' ' || junk[i] == '\t'; i++); */
      for (i=0; i<255 && (junk[i] == ' ' || junk[i] == '\t'); i++);
      if(junk[i]=='\n' || i==255) continue;

      if(strncmp("Markerdata",junk,10)==0){
	markerstuff = TRUE;
        break;
      }
      if (strncmp("Marker_",junk,7)==0) {
         fprintf(stderr,"No 'Markerdata' delimiter - aborting load...\n");
         exit(0);
      }
      if(strncmp("Contigdata",junk,10)==0){
	contigstuff = TRUE;
        break;
      }
      ctype = -1;
      for (i=0; i<clonetypenum && ctype==-1; i++)
         if(strncmp(clonetype[i],junk,strlen(clonetype[i]))==0) ctype = i;

      if(ctype!=-1){
	currfp = NULL;
	if (index != -1) { /* finish off last clone */
            if(clone.ctg == 0) singleton++;
            if (clone.creation_date.month==0) {
	       settime(&clone.creation_date);
	       settime(&clone.modified_date);
            }
                 /* ADD 4.5 28jun changed for sean */
            if (clone.seqstat == CANCELLED) {
                clone.seqtype = 0;
            }
            /* cari 1mar04 remove check for XAVOID */
	    array(acedata, index, CLONE) = clone ;
	}
	if (dequote(junk, clone.clone, CLONE_SZ-1)==0){
	  printf("ERROR string *%s* no DATA\n",junk);
	  exit(0);
	}
        max_clonesz = MaX(max_clonesz, strlen(clone.clone));
	if(!fppInsert(acedata,clone.clone,&index,cloneOrder)){
	  clone = arr(acedata, index, CLONE);    /* get original clone */
	  currfp = clone.fp;
	}
	else{
      clone.seq_hits = 0;
	  clone.class = ctype;
	  clone.next = -1;
	  clone.mattype = 0;
	  clone.parent = -1;
	  strcpy(clone.match,"        ");
	  clone.ctg = clone.oldctg = clone.x = clone.y = clone.highcol= clone.ibc=0 ;
      clone.size_bp = 0;
	  clone.remark = clone.fp_remark = NULL;
	  clone.chctg[0] = '\0';
	  currfp = clone.fp = NULL;
	  clone.marker = NULL;
	  clone.selected = FALSE;
	  clone.seqstat = clone.seqtype = 0;
          clone.creation_date.month=0;
          clone.creation_date.year=0;
          clone.creation_date.day=0;
          clone.creation_date.hour=0;
          clone.creation_date.minute=0;
	  tot_clones++;
          if (!Zbatch_flag)
             if (((tot_clones+1) % 1000 == 0)) {
                   fprintf(stderr, "Adding clone %d ......\r", tot_clones);
             }
	}
      }
      else if(strncmp("Gel",junk,3)==0 || strncmp("Fp_number",junk,9)==0)
      {
        if(currfp == NULL || strcmp(currfp->gelname, "-1")!=0) {
	  if (currfp == NULL) {
	      clone.fp = (struct fpdata *) messalloc(sizeof(struct fpdata));
              currfp = clone.fp;
          }
          else {
	      currfp->next = (struct fpdata *) messalloc(sizeof(struct fpdata));
	      currfp = currfp->next;
          }
	  currfp->next = NULL;
	  currfp->b1 = currfp->b2 = 0;
          strcpy(currfp->gelname,"-1");
	  strcpy(currfp->fpchar,"   ");
	}
        if(strncmp("Gel",junk,3)==0){
	  sscanf(junk,"Gel_number %s",currfp->gelname);
	}
	else {
	  fpnum = TRUE;
	  dequote(junk, currfp->fpchar, CLONE_SZ);
	  if(strlen(currfp->fpchar)==0)
	    strcpy(currfp->fpchar,"   ");
	}
      }
      else if(strncmp("Ban",junk,3)==0)
      {
         if (currfp == NULL)
            printf("bands & gels not in order expected\n");
         else {
            sscanf(junk,"Bands %d %d ",&currfp->b1,&currfp->b2);
            Proj.maxband = MaX(Proj.maxband, currfp->b2);
	    num_of_bands = MaX(num_of_bands, currfp->b1+currfp->b2-1);
         }
      }
      else if(strncmp("Map",junk,3)==0)
      {
	if (dequote(junk, name, 200)==0) continue;
	strcpy(clone.chctg,name);
	sscanf(clone.chctg,"ctg%d",&clone.ctg);
        max_contig = MaX(clone.ctg, max_contig);
	pos = strstr(junk,"Left");
	if(pos !=NULL) sscanf(pos,"Left %d.00",&clone.x);
	else{
	   pos = strstr(junk,"Right");
	   if(pos !=NULL) sscanf(pos,"Right %d.00",&clone.y);
	   pos = strstr(junk,"Oldctg"); /* 20june99 ADD */
	   if(pos !=NULL) sscanf(pos,"Oldctg %d",&clone.oldctg);
           else clone.oldctg = clone.ctg;
	   pos = strstr(junk,"CpM"); /* 20june99 ADD */
	   if(pos !=NULL) clone.ibc = 1;
           else if (clone.oldctg >= OLDCTG_MARK) { /* obsolete */
              clone.oldctg = clone.oldctg - OLDCTG_MARK;
              clone.ibc = 1;
           }
	}
      }
      else if(strncmp("Positive_",junk,9)==0)
      {
         if (dequote(junk, name, MARKER_SZ)==0) continue;
	 weak =  (strstr(junk, "_weak")!=NULL) ? 1 : 0;
         if  (strstr(junk, "New")!=NULL) new = 1;
         else if (strstr(junk, "CpM")!=NULL) new = 2;
         else new = 0;
         if ((markertype = get_fpc_marker(junk))== -1)
         {
             printf("line %d  keyword unknown %s",line, junk);
             continue;
         }
         if(clone.marker == NULL){
	   clone.marker  = (struct markertop *)
	     messalloc((sizeof(struct markertop)));
	   clone.marker->markerindex = -1;
	   strcpy(clone.marker->marker,name);
	   clone.marker->weak = weak;
	   clone.marker->new = new;
	   clone.marker->nextmarker = NULL;
         }
         else{
	   for (mtop = clone.marker; mtop->nextmarker != NULL;
	                        mtop = mtop->nextmarker);
	   mtop->nextmarker  = (struct markertop *)
	     messalloc((sizeof(struct markertop)));
	   mtop->nextmarker->nextmarker = NULL;
	   mtop->nextmarker->markerindex = -1;
	   mtop->nextmarker->weak = weak;
	   mtop->nextmarker->new = new;
	   strcpy(mtop->nextmarker->marker,name);
         }
      }
      else if(strncmp("App",junk,3)==0){
 	if (dequote(junk, clone.match, CLONE_SZ-1)){
	   clone.mattype = APPROX;
	   buried++;
        }
      }
      else if(strncmp("Exa",junk,3)==0){
 	if (dequote(junk, clone.match, CLONE_SZ-1)){
	    clone.mattype = EXACT;
	    buried++;
        }
      }
      else if(strncmp("Pse",junk,3)==0){
 	if (dequote(junk, clone.match, CLONE_SZ-1)){
	    clone.mattype = PSEUDO;
	    buried++;
        }
      }
      else if(strncmp("Remark",junk,6)==0){
        if (strstr(junk,"\"")==NULL) printf("Line %d: bad Remark\n",line);
        else {
	  if(clone.remark==NULL){
	    clone.remark = (struct remark *)messalloc((sizeof(struct remark)));
	    last = clone.remark;
	  }
	  else{
	    last->next  = (struct remark *)messalloc((sizeof(struct remark)));
	    last = last->next;
	  }
	  getcomment(junk, last->message, COMMENT_SZ);
	  last->next = NULL;
        }
      }
      else if(strncmp("Fpc_re",junk,6)==0){/* 14 mar 00 */
        if (strstr(junk,"\"")==NULL) printf("Line %d: bad Fpc_remark\n",line);
        else {
	  if(clone.fp_remark==NULL){
	    clone.fp_remark = (struct remark *)messalloc((sizeof(struct remark)));
	    last = clone.fp_remark;
	  }
	  else{
	    last->next  = (struct remark *)messalloc((sizeof(struct remark)));
	    last = last->next;
	  }
	  getcomment(junk, last->message, COMMENT_SZ);
	  last->next = NULL;
        }
      }
      else if(strncmp("Creation",junk,8)==0){
          int x;
          clone.creation_date.month=0;
	  x = sscanf(junk,"Creation_date %d %d %d %d %d",&clone.creation_date.year,
                 &clone.creation_date.month, &clone.creation_date.day,
                 &clone.creation_date.hour,&clone.creation_date.minute);
          if (x==1 || clone.creation_date.month==0) settime(&clone.creation_date);
      }
      else if(strncmp("Modified",junk,8)==0){
          int x;
          clone.modified_date.month=0;
	  x = sscanf(junk,"Modified_date %d %d %d %d %d",&clone.modified_date.year,
                &clone.modified_date.month, &clone.modified_date.day,
                &clone.modified_date.hour,&clone.modified_date.minute);
          if (x==1 || clone.modified_date.month==0)
          { /* compatiable with pre fpc v4 files */
              clone.modified_date.year = clone.creation_date.year;
              clone.modified_date.month = clone.creation_date.month;
              clone.modified_date.day = clone.creation_date.day;
              clone.modified_date.hour = clone.creation_date.hour;
              clone.modified_date.minute = clone.creation_date.minute;
          }
      }
      else if(strncmp("Shotgun",junk,7)==0){ /* ADD 19mar99 */
	  sscanf(junk,"Shotgun %s %s",type, status);
          for (i=0; i <seqstatnum  && clone.seqstat==0; i++)
              if (strncmp(status, seqstat[i], 2)==0) clone.seqstat = i;
          for (i=0; i <seqtypenum  && clone.seqtype==0; i++)
              if (strncmp(type, seqtype[i], 4)==0) clone.seqtype = i;
      }
      else { /* compatiable with pre fpc v4.1 files */
         for (i=0; i < seqstatnum  && clone.seqstat==0; i++)
             if (strncmp(junk, seqstat[i], 4)==0) {
                 clone.seqstat = i;
                 clone.seqtype = FULLX;
             }
         if(i>=seqstatnum && clone.seqstat==0)
           printf("Line %d: Bad or incorrect line: %s\n",line,junk);
      }
  }
  if (index != -1) { /* finish off last clone */
    array(acedata, index, CLONE) = clone;
    if(clone.ctg == 0) singleton++;
  }
  if(orig_clones != tot_clones && ctg_sets==1){
    printf("\nClones in header = %d, read in = %d. \n",
                orig_clones,tot_clones);
    if (Zbatch_flag) {
       printf("ABORT\n");
       exit(0);
    }
    if (!messQuery("Number of clones in header do not match number read. Continue?"))
        exit(0);
  }
  contigsAlloc(max_contig); /* security check */

/* WMN 9/27/06 compute the total number of bands;
    this is more reliable than using the header value which was sometimes 0 */

tot_bands = 0;
for (i = 0; i < arrayMax(acedata); i++) {
  clp = arrp(acedata,i,CLONE);  
  tot_bands += clp->fp->b2;  
}
Proj.tot_bands = tot_bands;



/*************************************************************************
 Parse markers
************************************************************************/

  marker = NULL;
  while(fgets(junk,255,fpace) != NULL && contigstuff==FALSE){
    line++;
    for (i=0; i<255 && (junk[i] == ' ' || junk[i] == '\t'); i++);
    if(junk[i]=='\n' || i==255) continue;

    if (strncmp(junk,"Clonedata",9)==0) {
        ctg_sets++;
        goto NEXT_SET;
    }
    if(strncmp("Contigdata",junk,10)==0){
        sscanf(junk,"Contigdata %d",&index);
        contigsAlloc(index);
	contigstuff = TRUE;
        break;
    }

    if(strncmp(junk,"Marker_",7)==0)
    {
      if ((markertype = get_fpc_marker(junk)) == -1) {
         markertype = markCLONE;
         printf("line %d unknown type %s",line, junk);
      }
      if (dequote(junk, name, MARKER_SZ)==0){
	printf("ERROR string *%s* no DATA\n",junk);
	exit(0);
      }
      max_markersz = MaX(max_markersz, strlen(name));
      if(fppInsert(markerdata,name,&index,markerOrder)){
        cnt_markers++;
        if (!Zbatch_flag)  /* cari 12/15/03 */
          if ((cnt_markers %1000)==0)
            fprintf(stderr, "Adding marker %d......\r", cnt_markers);
        strcpy(pt.marker, name);
	pt.type = markertype;
	pt.anchor_bin[0] = '\0';
        pt.anchor_pos = FLT_MIN; /* cari 20.5.4 */
	pt.pos = NULL;
        pt.cloneindex =  -1;
        pt.nextclone =  NULL;
        pt.count= 0;
        pt.anchor = FALSE;
        pt.colour = pt.box = pt.minicontigbox = 0;
        pt.status = AUTO;
        pt.weak = 0;
        pt.pos = NULL;
        pt.remark = NULL;
        array(markerdata,index,MARKER) = pt;
        marker = arrp(markerdata,index,MARKER);
      }
      else {
	  printf("duplicate marker %s listed\n",name);
          marker = NULL;
      }
      continue;
    }
    if (marker==NULL) continue;

    if(strncmp(junk,"Global_",7)==0) {
      if(strstr(junk,"Frame")!=0) marker->frame_type=FRAME;
      else marker->frame_type=PLACE;
      sscanf(junk,"Global_position %f",&x);

      /*fred 5/28/03 -- for backwards compatibility*/
      if(fwFlag){
	sprintf(tmp,"%.1f",x);
	tmp2 = (char *)&tmp[strlen(tmp)-5];
	sscanf(tmp2,"%f", &marker->anchor_pos);
	tmp[strlen(tmp)-5] = '\0';
	sprintf(marker->anchor_bin,"%s",tmp);
      }
      else{
        marker->anchor_bin[0]='\0';
	marker->anchor_pos=x;
      }
      marker->anchor = TRUE;
    }
    else if(strncmp(junk,"Anchor_bin",10)==0){
      if (dequote(junk, marker->anchor_bin, ANCHOR_BIN_SZ)==0){
	printf("ERROR string *%s* no DATA\n",junk);
	exit(0);
      }
    }
    else if(strncmp(junk,"Anchor_pos",7)==0){
      if(strstr(junk,"F")!=0) marker->frame_type=FRAME;
      else marker->frame_type=PLACE;
      sscanf(junk,"Anchor_pos %f",&marker->anchor_pos);
      marker->anchor = TRUE;
    }
    else if(strncmp(junk,"anchor",6)==0){
      ; /*Backwards compatibility*/
    }
    else if(strncmp(junk,"Map",3)==0){
      fprintf(stderr,"*** %s\n",junk);
    }
    else if(strncmp(junk,"User",4)==0){
      if(posptr != NULL)
       posptr->status = USER;
    }
    else if(strncmp(junk,"Sam",3)==0){
      if(posptr != NULL)
       posptr->status = SAM;
    }
    else if(strncmp("Remark",junk,6)==0){   /*fred 11/1/02*/
      if (strstr(junk,"\"")==NULL) printf("Line %d: bad Marker Remark\n",line);
      else {
        if(marker->remark==NULL){
          marker->remark = (struct remark *)messalloc((sizeof(struct remark)));
          last = marker->remark;
        }
	else{
	  last->next  = (struct remark *)messalloc((sizeof(struct remark)));
	  last = last->next;
	}
	getcomment(junk, last->message, COMMENT_SZ);
	last->next = NULL;
      }
    }
    else if(strncmp("Creation",junk,8)==0){
        int x;
	x = sscanf(junk,"Creation_date %d %d %d %d %d",
               &marker->creation_date.year,
               &marker->creation_date.month, &marker->creation_date.day,
               &marker->creation_date.hour,&marker->creation_date.minute);
        if (x==1 || marker->creation_date.month==0)
                      settime(&(marker->creation_date));
    }
    else if(strncmp("Modified",junk,8)==0){
        int x;
	x = sscanf(junk,"Modified_date %d %d %d %d %d",
               &marker->modified_date.year,
               &marker->modified_date.month, &marker->modified_date.day,
                &marker->modified_date.hour,&marker->modified_date.minute);
          if (x==1 || marker->modified_date.month==0)
          { /* compatiable with pre fpc v4 files */
              marker->modified_date.year = marker->creation_date.year;
              marker->modified_date.month = marker->creation_date.month;
              marker->modified_date.day = marker->creation_date.day;
              marker->modified_date.hour = marker->creation_date.hour;
              marker->modified_date.minute = marker->creation_date.minute;
          }
    }
    else if (strncmp("Clonedata",junk,9)==0)
         goto NEXT_SET;

    else printf("Line %d: Bad or incorrect line: %s\n",line,junk);
  }

  if (!Zbatch_flag)          /* cari 12/15/03 */
     printf("Linking clones to markers\n");
        /* make marker<-->clone links */
  for(i=0;i<arrayMax(acedata);i++){
    clp = arrp(acedata,i,CLONE);
    for (mtop = clp->marker; mtop!=NULL; mtop = mtop->nextmarker){
       if(!fppFind(markerdata,mtop->marker,&index, markerOrder)){
           printf("FPC ERROR could not find marker %s\n",mtop->marker);
           continue;
       }
       mtop->markerindex = index;

       marker = arrp(markerdata,index,MARKER);
       marker->count++;
       if(marker->cloneindex == -1) {
          marker->cloneindex = i;
          marker->weak = mtop->weak;
       }
       else {
          if (marker->nextclone==NULL) {
              marker->nextclone =
                (struct markerclone *)messalloc((sizeof(struct markerclone)));
              markclptr = marker->nextclone;
          }
          else {
              for (markclptr=marker->nextclone;
                   markclptr->nextclone!=NULL;
                   markclptr = markclptr->nextclone);
              markclptr->nextclone  =
                (struct markerclone *)messalloc((sizeof(struct markerclone)));
              markclptr= markclptr->nextclone;
          }
          markclptr->cloneindex = i;
          markclptr->weak = mtop->weak;
          markclptr->nextclone = NULL;
       }
    }
  }
  for(Marker_clone_max=flag=i=0;i<arrayMax(markerdata) && !flag;i++){
    marker = arrp(markerdata,i,MARKER);
    if (marker->cloneindex == -1) flag=1;
       /* cari 14.5.4 */
    if (marker->count> Marker_clone_max) Marker_clone_max =  marker->count;
  }
  if (flag==1) {
      register int k;
      markerdata2 = arrayCreate(arrayMax(markerdata),MARKER);
      for(k=i=0;i<arrayMax(markerdata);i++)
      {
         pt = arr(markerdata,i,MARKER);
         if (pt.cloneindex != -1 ) {
             array(markerdata2,k,MARKER) = pt;
             k++;
         }
         else
            fprintf(stderr,"Bad marker %s - remove\n",pt.marker);
      }
      arrayDestroy(markerdata);
      markerdata = markerdata2;
                        /* markercorrect indices **/
      for(i=0;i<arrayMax(acedata);i++){
        clp = arrp(acedata,i,CLONE);
        for (mtop = clp->marker; mtop != NULL; mtop = mtop->nextmarker) {
          if(fppFind(markerdata,mtop->marker,&index, markerOrder))
            mtop->markerindex = index;
          else
            printf("FPC ERROR clone %s no marker %s\n",clp->clone, marker->marker);
        }
      }
      markersinctgcount(); /* redo contig counts */
  }

/************************************************************************d
    Parse contigs
************************************************************************/
  if (contigstuff==FALSE) goto WINDUP;
  if (!Zbatch_flag) printf("Parse contig data\n");
  contigs[0].trace_msg[0]=contigs[0].chr_msg[0]=contigs[0].user_msg[0]='\0';

  while(fgets(junk,255,fpace) != NULL){
    line++;
    for (i=0; i<255 && (junk[i] == ' ' || junk[i] == '\t'); i++);
    if(junk[i]=='\n' || i==255) continue;
    if (strncmp("Seqdata",junk,7)==0) break;

    if (strncmp("Ctg",junk,3)==0) {
        sscanf(junk,"Ctg%d",&index);
        contigsAlloc(index);

        sscanf(junk,"Ctg%d %d/%d/%d %d:%d %s %d", &index3,
          &contigs[index].ctgdate.day, &contigs[index].ctgdate.month,
          &contigs[index].ctgdate.year, &contigs[index].ctgdate.hour,
          &contigs[index].ctgdate.minute, status, &contigs[index].ctgQs);
        if (strstr(junk,"ApproxQs")) contigs[index].approxQs = 1;
        else contigs[index].approxQs = 0;

        i = strlen(status)-1;
        if (contigs[index].ctgQs> 999999) contigs[index].ctgQs = -1;
        if (status[i] == '+') {
            contigs[index].ctgIBC = '+';
            status[i] = '\0';
        }
        for (i=0; i <ctgstatnum; i++)
            if (strncmp(status, ctgstat[i], 4)==0) {
                contigs[index].ctgstat = i;
                break;
            }
         /* Cari 22 oct 04 */
        if ((ptr = strstr(junk,"High")))
            sscanf(ptr,"High %d Avg %d Low %d", &contigs[index].high_score,
                   &contigs[index].avg_score,&contigs[index].low_score);
            /* CAS 2-2-3  PARSE old contig remark 6.4 */
        else if ((ptr = strstr(junk,"#"))!=NULL) {
            char tmp[200];
            ptr += 2;
            strcpy(tmp,ptr);
            if (strstr(tmp,CTGUSERMSG)!=NULL) {
                if (strstr(tmp,"]")!=NULL) {
                   for (j=0; tmp[j]!=']' && tmp[j]!='\0' && j < CTGMSG_SZ; j++)
                      contigs[index].chr_msg[j]=tmp[j];
                   contigs[index].chr_msg[j]=tmp[j];
                   contigs[index].chr_msg[++j]='\0';

                   for (k=0; tmp[j]!=':' && tmp[j]!='\0' && k < CTGMSG_SZ; j++, k++)
                      contigs[index].user_msg[k]= tmp[j];
                   contigs[index].user_msg[k]='\0';
                }
                else {
                   for (j=0; tmp[j]!=':' && tmp[j]!='\0' && j < CTGMSG_SZ; j++);
                      contigs[index].user_msg[j]=tmp[j];
                   contigs[index].user_msg[j]='\0';
                }
                for (; tmp[j]==':'; j++);
                for (k=0; tmp[j]!='\0' && k < CTGMSG_SZ; j++,k++)
                       contigs[index].trace_msg[k]=tmp[j];
                contigs[index].trace_msg[k-1]='\0';
            }
            else {
                strncpy(contigs[index].trace_msg,tmp, CTGMSG_SZ);
                j = strlen(contigs[index].trace_msg)-1;
                contigs[index].trace_msg[j] = '\0';

                strncpy(contigs[index].user_msg,tmp, CTGMSG_SZ);
                j = strlen(contigs[index].user_msg)-1;
                contigs[index].user_msg[j] = '\0';
            }
         }
      }
      else if(strncmp("Chr_remark",junk,7)==0){
         getcomment(junk, contigs[index].chr_msg, CTGMSG_SZ);
         if((ptr = strstr(junk,"Pos")))
               sscanf(ptr,"Pos %f",&contigs[index].chr_pos);
         if (strstr(junk,"NOEDIT")!=NULL) contigs[index].noedit_chr=1;
         if (strstr(junk,"NoAutoChr")!=NULL) contigs[index].noedit_chr=1;
         if (strstr(junk,"NoAutoPos")!=NULL) contigs[index].noedit_pos=1;
      }
      else if(strncmp("User_remark",junk,7)==0){
	    getcomment(junk, contigs[index].user_msg, CTGMSG_SZ);
      }
      else if(strncmp("Trace_remark",junk,7)==0){
	    getcomment(junk, contigs[index].trace_msg, CTGMSG_SZ);
      }

  } /* end main while loop */

  /* load sequence file lists */
  while(fgets(junk,255,fpace) != NULL){
    fpc_load_info_file(junk);
  }

/************************************************************/
WINDUP: ;
  if (max_clonesz==0) max_clonesz = CLONE_SZ;
  if (max_markersz==0) max_markersz = MARKER_SZ;
  filclose(fpace);
  max_contig = getcontigsmax();
  firstread = FALSE;
  fpcreadflag = TRUE;
  if(!projmerge){
    Pz_init();
    SetCtgForMatchingClones2();
    /*markercorrect();*/
    sortoutmarkersman();
    for(i=0;i<FPMAX;i++)
      cloneindex[i]= -1;

    markersinctgcount();

    getfppdata();

    for (maxindex=0, i=1; i<=max_contig; i++) if (contigs[i].count>0) maxindex++;
    fprintf(stdout,"Loaded: Contigs %d  Clones %d Buried %d Singletons %d  Markers %d\n",
                maxindex, tot_clones, buried, singleton, arrayMax(markerdata));
    fflush(stdout); /* cari 2/4/4/  for cronjob */
    dataloaded = TRUE;
  }
  update=FALSE;

  redo_sequence_placements();

  return(1);
}
/*****************************************************************
                         DEF: dequote
27/3/96 - use last charachters if too long
*********************************************************************/
int dequote(buf, name, len)
char *buf, *name;
int len;
{
int n, i;
char *p, *q, tmp[200];

    name[0] = '\0';
    if (strlen(buf)==0) return 0;
    p = strstr(buf,"\"");
    if (p==NULL) return 0;

    p++;
    q = strstr(p,"\"");
    if (p!= NULL && q != NULL) {
       for (n=0;p < q && n < 200; p++) {
         if (*p==' ') tmp[n++]='-';
         else tmp[n++] = *p;
       }
       tmp[n] = '\0';
    }
    else {
        fprintf(stderr,"Incorrect name %s\n",buf);
        return 0;
    }
    if (tmp[0] == '\0') return 0;

    if (strlen(tmp) > len) {
       for (i=len, n = strlen(tmp); i >=0; i--, n--)
            name[i] = tmp[n];
       fprintf(stderr,"Left truncated %s from line %s",name, buf);
    }
    else strcpy(name, tmp);
return 1;
}

/*******************************************************************
                         DEF: getcomment
CAS 2-2-3 will sending a size, but not using it.
*********************************************************************/
void getcomment(buf, comment, size)
char *buf, *comment;
int size;
{
int n;
char *p, *q;

    p = strstr(buf,"\"");
    p++;
    q = strstr(p,"\"");
    if (p!= NULL && q != NULL) {
       for (n=0;p != q && n < size; p++) comment[n++] = *p;
       comment[n] = '\0';
    }
    else fprintf(stderr,"Bad Bad comment %s\n",buf);
    /* complains if exactly right size
    if (n==size) fprintf(stderr,"Long comment %s - truncated\n",buf);*/
}

/**************************************************************
                   DEF: SetCtgForMatchingClones2
**************************************************************/
void SetCtgForMatchingClones2()
/* This routine searches searches for the approxiamate and exact matches.*/
/* The clones that are these, will locate there "Mothers" and load their data */
{
  int i,max,index,j;
  CLONE *clone,*tmp, *parent;

  max= arrayMax(acedata);

  for(i=0;i<max;i++){

    clone =  arrp(acedata, i, CLONE);
    clone->next = -1;
    if(clone->clone[0] == '!') continue;

                    /* set up clone links for each contig */
    j = clone->ctg;
    contigsAlloc(j);
    if(contigs[j].count > 0){
	tmp = arrp(acedata,contigs[j].last,CLONE);
	tmp->next = i ;
	contigs[j].left = MiN(contigs[j].left, clone->x);
	contigs[j].right = MaX(contigs[j].right, clone->y);
     }
     else{
	contigs[j].start = i;
	contigs[j].ctg = clone->ctg;
	contigs[j].left = clone->x;
	contigs[j].right = clone->y;
     }
     contigs[j].last = i ;
     contigs[j].count++;
     AddToCtgSeq(clone,j);

                    /** find parent index for buried clone **/
     if(clone->match[0] != ' '){
        if(!fppFind(acedata,clone->match,&index, cloneOrder)) {
	    printf("FPC ERROR could not find parent %s for child %s\n",
                  clone->match,clone->clone);
	  clone->mattype = 0;
	  clone->parent = -1;
	  strcpy(clone->match,"        ");
        }
        else{
	   clone->parent = index;
	   parent = arrp(acedata,index,CLONE);
	   if(clone->mattype != PSEUDO)
	     parent->mattype = PARENT;
	   else if(parent->mattype != PARENT)
	     parent->mattype = PSPARENT;
                                   /* sanity checks */
	   if(clone->ctg != parent->ctg) {
             printf("Warn: Buried %s not in same ctg as parent %s - unbury\n",
	         clone->clone, parent->clone);
             unbury(i);
           }
           if(strncmp(parent->match,"   ",3)) {
	     printf("Warn: clone %s has parent %s who has parent %s\n",
	        parent->clone ,clone->clone,
	       arrp(acedata,clone->parent, CLONE)->clone);
             unbury(i);
           }
       }
    }
  }
}

/*****************************************************************
                         DEF: sortoutmarkersman
*********************************************************************/
void sortoutmarkersman()
{
  int i;
  CLONE *clone;
  MARKER *marker;
  struct markertop *markertop;
  struct markerctgpos *posptr;
  BOOL found = FALSE;

  for(i=0;i<arrayMax(acedata);i++){
    clone = arrp(acedata,i,CLONE);
    if(clone->ctg == 0) continue;

    for (markertop = clone->marker; markertop!= NULL;
	                        markertop = markertop->nextmarker)
    {
	marker = arrp(markerdata,markertop->markerindex,MARKER);
	posptr = marker->pos;
	found = FALSE;
	if(posptr == NULL){
	   marker->pos = (struct markerctgpos *)
	     messalloc((sizeof(struct markerctgpos)));
	   posptr= marker->pos;
	   posptr->ctg = clone->ctg;
	   posptr->status = AUTO;
	   posptr->next = NULL;
	}
	else{
	   while(!found){
	     if(posptr->ctg == clone->ctg)
	        found = TRUE;
	     if(posptr->next != NULL)
	        posptr = posptr->next;
	     else
	        break;
	   }
	   if(!found){
	      posptr->next = (struct markerctgpos *)
	          messalloc((sizeof(struct markerctgpos)));
	      posptr= posptr->next;
	      posptr->ctg = clone->ctg;
	      posptr->status = AUTO;
	      posptr->next = NULL;
	  }
	}
     }
  }
  setmarkerposman();
}
/*****************************************************************
                         DEF: setmarkerposman
*********************************************************************/
void setmarkerposman()
{
  int l;
  struct markerclone *p;
  struct markerctgpos *pos=NULL;
  struct marker *marker;
  CLONE *clone;
  struct posman {
      int left, right, ctg;
  } *pt, tmp;
  int *stack, s;
  int k, depth=0, npt, i, j, ctg;
  int x=0, y=0, save_depth=0;
  int num_alloc = Marker_clone_max;

  if (Marker_clone_max==0) num_alloc = 100;
  pt = (struct posman *) calloc(num_alloc, sizeof(struct posman));
  NOMEM2a(pt, "Setting marker position",num_alloc, sizeof(struct posman));
  stack = (int *) calloc(num_alloc, sizeof(int));
  NOMEM2a(pt, "Setting marker stack",num_alloc, sizeof(int));

/* find all clones for marker */
  for(l=0;l<arrayMax(markerdata);l++)
  {
    marker = arrp(markerdata,l,MARKER);
    clone = arrp(acedata,marker->cloneindex,CLONE);
    p = marker->nextclone;
    npt=0;
    if(clone->ctg != 0){
       pt[npt].ctg = clone->ctg;
       pt[npt].left = clone->x;
       pt[npt].right = clone->y;
       npt++;
     }
    while(p != NULL){
      clone = arrp(acedata,p->cloneindex,CLONE);
      if (npt == num_alloc) {
        num_alloc+=100;
        pt = (struct posman *) realloc(pt, num_alloc*sizeof(struct posman));
        NOMEM2a(pt, "Setting marker position",num_alloc, sizeof(struct posman));
        stack = (int *) realloc(stack, num_alloc*sizeof(int));
        NOMEM2a(pt, "Setting marker stack",num_alloc, sizeof(int));
      }
      if(clone->ctg != 0){
	pt[npt].ctg = clone->ctg;
	pt[npt].left = clone->x;
	pt[npt].right = clone->y;
	npt++;
      }
      p = p->nextclone;
    }
/* sort by ctg and left end */
    if(npt == 0) /*  if marker belongs to clones in ctg0, no processing needed */
      continue;
    for (i=0; i<npt-1; i++)
      for (j=i+1; j<npt; j++)
	if (pt[i].ctg > pt[j].ctg ||
	    (pt[i].ctg == pt[j].ctg && pt[i].left > pt[j].left)) {
	  tmp = pt[i];
	  pt[i] = pt[j];
	  pt[j] = tmp;
	}
/* for each ctg, position */
    ctg  = -1;

   for (i=0; i<npt; i++) {
     if (ctg != pt[i].ctg)
     {
       if(ctg == -1){
	 ctg = pt[i].ctg;
       }
       else{
	 if (depth > save_depth)
	   if(pos->status == AUTO)
	     pos->pos = (x+y) >> 1;
       }
       ctg = pt[i].ctg;
       pos = marker->pos;
       if (pos==NULL) {
        fprintf(stderr,"erro on %s ctg\n",marker->marker);
        continue;
       }
       while(pos->ctg != ctg && pos != NULL)
	 pos = pos->next;
       if(pos == NULL)
	 printf("FPC ERROR MARKER BIT\n");
       x = pt[i].left;
       y = pt[i].right;
       stack[0] = y;
       if(pos->status == AUTO)
	 pos->pos = (x+y) >> 1;
       ctg = pos->ctg = pt[i].ctg;
       depth = save_depth = 1;
     }
     else if (pt[i].left <= y) {
        if (depth == num_alloc) {
           printf("Marker %s hits over %d clones - cannot continue. \n",
                marker->marker, num_alloc);
           exit(0);
        }
        stack[depth++] = pt[i].right;
	x = MaX(x, pt[i].left);
	y = MiN(y, pt[i].right);
     }
     else {
	if (depth > save_depth) {
	  save_depth = depth;
	  if(pos->status == AUTO)
		pos->pos = (x+y) >> 1;
	}
        x = pt[i].left;
        y = pt[i].right;
        stack[depth++] = y;
        for (j=-1, k=s=0; s< depth; s++)
        {
           if (stack[s] < x) {
              stack[s] = -1;
              if (j == -1) j = s;
           }
           else {
              k++;
              y = MiN(y, stack[s]);
              if (stack[j]== -1) {
                 stack[j] = stack[s];
                 stack[s] = -1;
                 while (stack[j]!=-1) j++;
              } else j = s;
           }
        }
	depth=k;
      }
    }
    if (depth > save_depth) {
      if(pos->status == AUTO)
	pos->pos = (x+y) >> 1;
    }
  } /* end loop through markers */
  free(pt);
  free(stack);
  for(Marker_clone_max=i=0;i<arrayMax(markerdata);i++){
    marker = arrp(markerdata,i,MARKER);
    if (marker->count> Marker_clone_max) Marker_clone_max =  marker->count;
  }
  if (!Zbatch_flag) printf("Maximum clones for a marker %d\n",Marker_clone_max);
}
/*********************************************************/
void getfppdata()
{
  load_layout();  /*fred 4/14/03 Get defaults for new display*/
}

void savefppdata()
{
  write_fpp_file(); /*fred 4/15/03 Write new display layouts*/
}
